// Copyright (C) 1953-2022 NUDT
// Verilog module name - packet_mirror
// Version: V4.0.20221216
// Created:
//         by - fenglin
////////////////////////////////////////////////////////////////////////////
// Description:
//         packet_mirror
///////////////////////////////////////////////////////////////////////////
`timescale 1ns/1ps

module packet_mirror
(
		i_clk,
		i_rst_n,
		
		iv_pkt_abstract,
		i_pkt_abstract_wr,
        o_fifo_full,	
		iv_dmac,
		iv_smac,
		ov_mirror_pkt,
		o_mirror_pkt_wr	
);
input 				i_clk;
input	            i_rst_n;
	            
input	[127:0]		iv_pkt_abstract;
input               i_pkt_abstract_wr;
input   [47:0]	    iv_dmac;
input   [47:0]	    iv_smac;
output              o_fifo_full;	                           
output  reg  [8:0]	ov_mirror_pkt;
output  reg         o_mirror_pkt_wr;
wire				r_fifo_full;
reg                 rdreq;
wire  [127:0]       pkt_abstract_data;
reg   [127:0]       rv_pkt_abstract_data;
wire  [5:0]         fifo_cont;
reg         [10:0]  sendbyte_cnt;

reg         [3:0]   pm_state;
localparam  IDLE_S                = 4'd0,
            ENND_TSMPHEAD_S       = 4'd1,
            SEND_DATA1_S          = 4'd2,
			SEND_DATA2_S          = 4'd3,
			SEND_DATA3_S          = 4'd4,
			SEND_DATA4_S          = 4'd5,
			DELAY_S               = 4'd6;
			
assign  o_fifo_full = r_fifo_full;

always @(posedge i_clk or negedge i_rst_n)begin
    if(!i_rst_n)begin      
        ov_mirror_pkt             <= 9'd0;
        o_mirror_pkt_wr           <= 1'b0;                                   
		rdreq                     <= 1'b0; 
        sendbyte_cnt		      <= 11'b0;
		rv_pkt_abstract_data	  <= 128'b0;	
        pm_state                  <= IDLE_S;
    end
    else begin
        case(pm_state)
            IDLE_S:begin	
				if((fifo_cont>6'd4)||(r_fifo_full==1))begin
					ov_mirror_pkt       <= {1'b1,iv_dmac[47:40]};
					o_mirror_pkt_wr     <= 1'b1;
					sendbyte_cnt		<= sendbyte_cnt+1'b1; 
					pm_state            <= ENND_TSMPHEAD_S;
				end
				else begin
					ov_mirror_pkt       <= 9'd0;
					o_mirror_pkt_wr     <= 1'b0;
					sendbyte_cnt		<= 11'b0; 
					pm_state            <= IDLE_S;		
				end
			end
            ENND_TSMPHEAD_S:begin	
				o_mirror_pkt_wr     <= 1'b1;
				sendbyte_cnt		<= sendbyte_cnt+1'b1; 
				case(sendbyte_cnt)
					11'd1: ov_mirror_pkt <= {1'b0,iv_dmac[39:32]};
					11'd2: ov_mirror_pkt <= {1'b0,iv_dmac[31:24]};
					11'd3: ov_mirror_pkt <= {1'b0,iv_dmac[23:16]};						
					11'd4: ov_mirror_pkt <= {1'b0,iv_dmac[15:8]};
					11'd5: ov_mirror_pkt <= {1'b0,iv_dmac[7:0] };
					11'd6: ov_mirror_pkt <= {1'b0,iv_smac[47:40]};
					11'd7: ov_mirror_pkt <= {1'b0,iv_smac[39:32]};						
					11'd8: ov_mirror_pkt <= {1'b0,iv_smac[31:24]};											
					11'd9: ov_mirror_pkt <= {1'b0,iv_smac[23:16]};
					11'd10: ov_mirror_pkt<= {1'b0,iv_smac[15:8]};
					11'd11: ov_mirror_pkt<= {1'b0,iv_smac[7:0] };
					11'd12: ov_mirror_pkt<= 9'hff;
					11'd13: ov_mirror_pkt<= 9'h01;
					11'd14: ov_mirror_pkt<= 9'h08;
					11'd15: ov_mirror_pkt<= 9'h01;
					default: begin
						ov_mirror_pkt<= ov_mirror_pkt;
						o_mirror_pkt_wr     <= 1'b0;
						sendbyte_cnt		<= sendbyte_cnt;
					end						
				endcase	
				if(sendbyte_cnt==11'd15)begin
					rdreq      <= 1'b1;
					rv_pkt_abstract_data<= pkt_abstract_data;
					pm_state   <= SEND_DATA1_S;	
				end
				else begin
					rdreq      <= 1'b0;
					rv_pkt_abstract_data<= rv_pkt_abstract_data;
					pm_state   <= ENND_TSMPHEAD_S;				
				end
			end	
			SEND_DATA1_S:begin	
				o_mirror_pkt_wr     <= 1'b1;
				sendbyte_cnt		<= sendbyte_cnt+1'b1; 
				case(sendbyte_cnt)
					11'd16: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[127:120]};
					11'd17: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[119:112]};
					11'd18: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[111:104]};						
					11'd19: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[103:96]};
					11'd20: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[95:88]};
					11'd21: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[87:80]};
					11'd22: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[79:72]};					
					11'd23: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[71:64]};										
					11'd24: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[63:56]};
					11'd25: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[55:48]};
					11'd26: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[47:40]};
					11'd27: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[39:32]};
					11'd28: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[31:24]};
					11'd29: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[23:16]};
					11'd30: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[15:8]};
					11'd31: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[7:0]};
					default: begin                            
						ov_mirror_pkt<= ov_mirror_pkt;
						o_mirror_pkt_wr     <= 1'b0;
						sendbyte_cnt		<= sendbyte_cnt;
					end						
				endcase	
				if(sendbyte_cnt==11'd31)begin
					rdreq      <= 1'b1;
					rv_pkt_abstract_data<= pkt_abstract_data;
					pm_state   <= SEND_DATA2_S;	
				end
				else begin
					rdreq      <= 1'b0;
					rv_pkt_abstract_data<= rv_pkt_abstract_data;
					pm_state   <= SEND_DATA1_S;				
				end
			end	
			SEND_DATA2_S:begin	
				o_mirror_pkt_wr     <= 1'b1;
				sendbyte_cnt		<= sendbyte_cnt+1'b1; 
				case(sendbyte_cnt)
					11'd32: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[127:120]};
					11'd33: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[119:112]};
					11'd34: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[111:104]};							
					11'd35: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[103:96]};
					11'd36: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[95:88]};
					11'd37: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[87:80]};
					11'd38: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[79:72]};						
					11'd39: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[71:64]};											
					11'd40: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[63:56]};
					11'd41: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[55:48]};
					11'd42: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[47:40]};
					11'd43: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[39:32]};
					11'd44: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[31:24]};
					11'd45: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[23:16]};
					11'd46: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[15:8]};
					11'd47: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[7:0]};
					default: begin                            
						ov_mirror_pkt<= ov_mirror_pkt;
						o_mirror_pkt_wr     <= 1'b0;
						sendbyte_cnt		<= sendbyte_cnt;
					end						
				endcase	
				if(sendbyte_cnt==11'd47)begin
					rdreq      <= 1'b1;
					rv_pkt_abstract_data<= pkt_abstract_data;
					pm_state   <= SEND_DATA3_S;	
				end
				else begin
					rdreq      <= 1'b0;
					rv_pkt_abstract_data<= rv_pkt_abstract_data;
					pm_state   <= SEND_DATA2_S;				
				end
			end	
			SEND_DATA3_S:begin	
				o_mirror_pkt_wr     <= 1'b1;
				sendbyte_cnt		<= sendbyte_cnt+1'b1; 
				case(sendbyte_cnt)
					11'd48: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[127:120]};
					11'd49: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[119:112]};
					11'd50: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[111:104]};							
					11'd51: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[103:96]};
					11'd52: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[95:88]};
					11'd53: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[87:80]};
					11'd54: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[79:72]};						
					11'd55: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[71:64]};											
					11'd56: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[63:56]};
					11'd57: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[55:48]};
					11'd58: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[47:40]};
					11'd59: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[39:32]};
					11'd60: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[31:24]};
					11'd61: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[23:16]};
					11'd62: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[15:8]};
					11'd63: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[7:0]};
					default: begin                            
						ov_mirror_pkt<= ov_mirror_pkt;
						o_mirror_pkt_wr     <= 1'b0;
						sendbyte_cnt		<= sendbyte_cnt;
					end						
				endcase	
				if(sendbyte_cnt==11'd63)begin
					rdreq      <= 1'b1;
					rv_pkt_abstract_data<= pkt_abstract_data;
					pm_state   <= SEND_DATA4_S;	
				end
				else begin
					rdreq      <= 1'b0;
					rv_pkt_abstract_data<= rv_pkt_abstract_data;
					pm_state   <= SEND_DATA3_S;				
				end
			end	
			SEND_DATA4_S:begin	
				o_mirror_pkt_wr     <= 1'b1;
				case(sendbyte_cnt)
					11'd64: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[127:120]};
					11'd65: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[119:112]};
					11'd66: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[111:104]};						
					11'd67: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[103:96]};
					11'd68: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[95:88]};
					11'd69: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[87:80]};
					11'd70: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[79:72]};						
					11'd71: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[71:64]};											
					11'd72: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[63:56]};
					11'd73: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[55:48]};
					11'd74: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[47:40]};
					11'd75: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[39:32]};
					11'd76: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[31:24]};
					11'd77: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[23:16]};
					11'd78: ov_mirror_pkt <= {1'b0,rv_pkt_abstract_data[15:8]};
					11'd79: ov_mirror_pkt <= {1'b1,rv_pkt_abstract_data[7:0]};
					default: begin                            
						ov_mirror_pkt<= ov_mirror_pkt;
						o_mirror_pkt_wr     <= 1'b0;
						sendbyte_cnt		<= sendbyte_cnt;
					end						
				endcase	
				if(sendbyte_cnt==11'd79)begin
					rdreq       <= 1'b0;
					sendbyte_cnt<= 11'b0;
					rv_pkt_abstract_data	  <= 128'b0;
					pm_state   <= DELAY_S;	
				end
				else begin
					sendbyte_cnt<= sendbyte_cnt+1'b1; 
					rdreq      <= 1'b0;
					rv_pkt_abstract_data<= rv_pkt_abstract_data;
					pm_state   <= SEND_DATA4_S;				
				end
			end	
			DELAY_S:begin
				ov_mirror_pkt       <= 9'd0;
				o_mirror_pkt_wr     <= 1'b0;			
				if(sendbyte_cnt<11'd11)begin
					sendbyte_cnt	<= sendbyte_cnt+1'b1; 
					pm_state        <= DELAY_S;				
				end
				else begin
					sendbyte_cnt		<= 11'b0; 
					pm_state            <= IDLE_S;					
				end		
			end
            default:begin             
				ov_mirror_pkt       <= 9'd0;
				o_mirror_pkt_wr     <= 1'b0;
				sendbyte_cnt		<= 11'b0; 
				pm_state            <= IDLE_S;	             
            end
        endcase			
	end
end
/*
asyncfifo_w128d64_aclr_showahead mirror_abstract_cache(
  .data  (iv_pkt_abstract),
  .wrreq (i_pkt_abstract_wr),
  .rdreq (rdreq),
  .clock (i_clk   ),
  .aclr  (!i_rst_n),
  .q     (pkt_abstract_data),   
  .usedw (fifo_cont),
  .full  (r_fifo_full),
  .empty ()
);*/

asyncfifo_w128d64_aclr_showahead mirror_abstract_cache(
.srst      (!i_rst_n),                    //Reset the all signal
.din       (iv_pkt_abstract),                       //The Inport of data 
.rd_en     (rdreq),       //active-high
.clk       (i_clk),                       //ASYNC WriteClk(), SYNC use wrclk
.wr_en     (i_pkt_abstract_wr),                     //active-high
.dout      (pkt_abstract_data),   //The output of data
.full      (r_fifo_full),                            //Write domain full 
.empty     (),    //Write domain empty
.data_count(fifo_cont)                            //Read-usedword
);

endmodule 